package props

import (
	"reflect"

	"gitee.com/night-tc/gen-entity/gencode"
	"gitee.com/night-tc/gobige/logger"
	"gitee.com/night-tc/gobige/msgdef"
)

/*
基于配置表加载进来的结构
用与标记字段状态，字段的基础信息的结构

*/

// Def 独立的实体定义
type Def struct {
	Name         string               //主类型名字
	FieldsByID   map[uint32]*FieldDef //key是Index的字段map
	FieldsByName map[string]*FieldDef //key是Name的字段map
}

func newDef() *Def {
	return &Def{
		FieldsByID:   make(map[uint32]*FieldDef),
		FieldsByName: make(map[string]*FieldDef),
	}
}

// 填充数据
func (def *Def) fill(nttdata *gencode.Entity) error {
	def.Name = nttdata.Name
	nttdata.Init()
	for _, v := range nttdata.FieldMap {
		fd := new(FieldDef)
		fd.SubTypes = make(map[string]struct{})
		fd.Desc = v.Desc
		fd.Name = v.Name
		fd.Index = v.Index + nttdata.StartIndex
		fd.SaveSrv = v.Save
		if fd.SaveSrv == 0 {
			//没有保存服务器的时候，才获取配置main
			fd.MainSrv = v.Main
		} else {
			// 有保存服务器的时候，主管理服务器就是保存服务器
			fd.MainSrv = fd.SaveSrv
		}
		fd.TypeName = v.MsgName
		fd.IsSync = true
		fd.RefType = getTypeByStr(fd.TypeName)
		def.FieldsByName[fd.Name] = fd
		def.FieldsByID[fd.Index] = fd
	}

	for _, srv := range nttdata.Server {
		for _, fname := range srv.Fields {
			fd := def.FieldsByName[fname]
			fd.WatchSrvs = append(fd.WatchSrvs, srv.SType)
		}
	}
	for _, sub := range nttdata.SubTypes {
		for _, fname := range sub.Fields {
			fd := def.FieldsByName[fname]
			fd.SubTypes[sub.Name] = struct{}{}
		}
	}
	for _, fname := range nttdata.Client.Fields {
		fd := def.FieldsByName[fname]
		fd.IsClient = true
	}
	for _, fname := range nttdata.Mrole.Fields {
		fd := def.FieldsByName[fname]
		fd.IsMRole = true
	}

	return nil
}

// 按名字获取类型
func getTypeByStr(st string) reflect.Type {
	var t reflect.Type
	switch st {
	case "int8":
		t = reflect.TypeOf(int8(0))
	case "int16":
		t = reflect.TypeOf(int16(0))
	case "int32":
		t = reflect.TypeOf(int32(0))
	case "int64":
		t = reflect.TypeOf(int64(0))
	case "byte":
		t = reflect.TypeOf(byte(0))
	case "uint8":
		t = reflect.TypeOf(uint8(0))
	case "uint16":
		t = reflect.TypeOf(uint16(0))
	case "uint32":
		t = reflect.TypeOf(uint32(0))
	case "uint64":
		t = reflect.TypeOf(uint64(0))
	case "float32":
		t = reflect.TypeOf(float32(0))
	case "float64":
		t = reflect.TypeOf(float64(0))
	case "string":
		t = reflect.TypeOf("")
	case "bool":
		t = reflect.TypeOf(false)
	default:
		msgd, err := msgdef.GetTypeMgr().GetMsgDefByName(st)
		if err != nil {
			logger.Errorf("getTypeByStr:%s %v", st, err)
		}
		t = msgd.Typ
	}

	return t
}

////////////////////////////////////////////////////////////////

// 单个字段
type FieldDef struct {
	Name     string              //字段名字
	Index    uint32              //字段的唯一ID
	Desc     string              //字段说明
	TypeName string              //类型名字
	SubTypes map[string]struct{} //哪些子类型有这个字段

	WatchSrvs []uint32 //关心的服务器类型
	IsClient  bool     //是否其他客户端需要
	IsMRole   bool     //是否自己客户端需要
	SaveSrv   uint32   //做数据落地的服务器类型
	MainSrv   uint32   // 主管理的服务器类型
	IsSync    bool     //当这个字段值发生变化时，是否需要同步给别的服务器

	RefType reflect.Type //实例类型
}
